package services

import (
	"errors"
	"fmt"
	database "hft/Database"
	"hft/Database/admin"
	"hft/Http/Models/dao"
	"hft/Http/Models/request"
	"hft/Http/Models/response"
	"hft/Http/Services/base"
	utils "hft/Http/Utils"
	"hft/e"
	"hft/global"
	"hft/tools"
	"regexp"
	"strings"

	"gorm.io/gorm"
)

type Account struct{}

func (a *Account) AddAccount(claims tools.BaseClaims, account *request.Account) (err error) {

	var SearchRegion *admin.Region
	var roles []*admin.Role
	var parentAccount *admin.Account
	var nowRole *admin.Role
	var manager *admin.Account

	err2 := tools.AliyunSmsTool.VerifyValid("ADD_ACCOUNT_", account.Phone, account.Code)

	if err2 != nil {
		return err2
	}

	res1, err1 := tools.ValidIDCard(account.IDCard, account.RealName)

	if res1.Data.ResponseCode != "0" {
		return errors.New(e.IDCardNotPass)
	}

	if err1 != nil {
		return errors.New(e.InValidInfo)
	}

	err = global.OC_DB.Transaction(func(tx *gorm.DB) error {

		parentAccount, err = base.FindAccount(claims, tx)

		if err != nil {
			return err
		}

		err = tx.Where("id = ?", account.RoleId).First(&nowRole).Error

		if err != nil {
			return errors.New(e.RoleNotExist)
		}

		if account.Belong == 0 { // 如果当前的belong为0 默认属于当前这个账号，
			tx.Where("p_id = ?", parentAccount.RoleId).Find(&roles)
			var roleArr []uint //获取当前可以配置的角色
			for _, v := range roles {
				roleArr = append(roleArr, v.ID)
			}
			if !tools.ContainsUint(roleArr, account.RoleId) { //如果你要添加的角色不在该子角色范围内，那么就不予添加
				return errors.New("你所配置的角色不在当前的范围内，无法配置")
			}
			account.PID = parentAccount.ID
			account.Link = fmt.Sprintf("%v%v,", parentAccount.Link, account.RoleId)
			account.AccountLink = fmt.Sprintf("%v%v,", parentAccount.AccountLink, parentAccount.ID)
			account.RegionLink = parentAccount.RegionLink
		} else {

			err = tx.Where("id = ?", account.Belong).First(&SearchRegion).Error

			if err != nil {
				return errors.New("无该地区信息")
			}

			if SearchRegion.ManageId == 0 {
				return errors.New("该地区尚未设置代理人，请先设置代理人账号")
			}

			tx.Where("id = ?", SearchRegion.ManageId).First(&manager) //找出地区代理人

			res := tx.Where("p_id = ?", manager.RoleId).Find(&roles)

			if res.Error != nil {
				return errors.New("未知错误")
			}

			var rolesId []uint

			for _, v := range roles {
				rolesId = append(rolesId, v.ID)
			}

			if !tools.ContainsUint(rolesId, account.RoleId) {
				return errors.New("你要创建的账号不在该账号的管辖范围内")
			}
			account.PID = manager.ID
			account.Link = fmt.Sprintf("%v%v,", manager.Link, account.RoleId)
			account.AccountLink = fmt.Sprintf("%v%v,", manager.AccountLink, manager.ID)
			account.RegionLink = manager.RegionLink
		}
		account.RoleName = nowRole.RoleName

		var parentRole *admin.Role

		tx.First(&parentRole, parentAccount.RoleId) //找出父角色

		res := tx.Model(&admin.Account{}).Where("username = ?", account.Username).Or("phone = ?", account.Phone).FirstOrCreate(&account.Account)

		if res.Error != nil {
			return errors.New("未知错误500")
		}

		if res.RowsAffected == 0 {
			return errors.New("账号或手机号已存在")
		}

		err = tx.Create(&account).Error

		if err != nil {
			return errors.New("未知错误500")
		}
		// var newAccount *admin.Account
		// tx.Where("username = ?", account.Username)
		// var dir = &file.Dir{
		// 	Link: ",",
		// 	AccountID: ,
		// }
		// 创建目录
		// fileopera.CreateDirSystem(account.Username)
		// fileopera.CreateRoot(account.Username)

		return nil

	})

	return err
}

func (a *Account) EditAccount(account *request.Account) (err error) {

	var SearchAccount *admin.Account

	var searchRole *admin.Role

	err = global.OC_DB.First(&SearchAccount, account.ID).Error

	if err != nil {
		return errors.New("无该账号存在，请先创建")
	}

	global.OC_DB.First(&searchRole, SearchAccount.RoleId)

	err = global.OC_DB.Transaction(func(tx *gorm.DB) error {

		err2 := tools.AliyunSmsTool.VerifyValid("ADD_ACCOUNT_", account.Phone, account.Code)

		if err2 != nil {
			return err2
		}

		res1, err1 := tools.ValidIDCard(account.IDCard, account.RealName)

		if res1.Data.ResponseCode != "0" {
			return errors.New("身份证验证不通过")
		}

		if err1 != nil {
			return errors.New("未知错误")
		}

		err = global.OC_DB.Model(&admin.Account{}).Where("id = ?", account.ID).Updates(&admin.Account{
			Base:     database.Base{ID: account.ID, Sort: account.Sort},
			Username: account.Username,
			Password: account.Password,
			// NickName: account.NickName,
			Avatar:   account.Avatar,
			IDCard:   account.IDCard,
			Status:   account.Status,
			Phone:    account.Phone,
			RealName: account.RealName,
		}).Error

		if err != nil {
			return errors.New("手机号已注册")
		}

		// if searchRole.NeedAccountAudit {
		// 	err = AuditService.CreateAccountAudit(int(account.ID), SearchAccount, searchRole, tx)

		// 	if err != nil {
		// 		return err
		// 	}
		// }

		return nil
	})

	return err

}

func (a *Account) GetAccountInfo(claims tools.BaseClaims) (account *response.AccountInfo, err error) {

	var SearchAccount *admin.Account

	err = global.OC_DB.Scopes(dao.ParseAccountDao.Parse(claims, global.OC_DB)).Preload("Role").First(&SearchAccount).Error

	if err != nil {
		return nil, errors.New("无该账号信息")
	}

	belongName := dao.GetBelongDao.GetBelongFromAccount(SearchAccount.RegionLink, global.OC_DB)

	var data = &response.AccountInfo{
		Username: SearchAccount.Username,
		Avatar:   SearchAccount.Avatar,
		// NickName: SearchAccount.NickName,
		Phone:    SearchAccount.Phone,
		Belong:   belongName,
		Prefix:   global.OC_CONFIG.AliyunOSS.BucketUrl,
		RoleName: SearchAccount.Role.RoleName,
	}

	return data, err
}

func (a *Account) GetAccountList(claims tools.BaseClaims, paginate *request.AccountPage) (data *utils.Page, err error) {

	var SearchAccount *admin.Account

	var accounts []*admin.Account

	err = global.OC_DB.Transaction(func(tx *gorm.DB) error {

		if err := tx.Where("username = ?", claims.Username).First(&SearchAccount).Error; err != nil {
			return errors.New("无该账户信息")
		} else {
			tx.Scopes(dao.GetAccountDao.GetAccountList(SearchAccount, paginate, tx)).Find(&accounts).Scopes(dao.GetCount(tx)).Count(&paginate.Total)

			paginate.Data = accounts

			return nil

		}
	})

	return &paginate.Page, err
}

func (a *Account) GetAreaByAccount(claims tools.BaseClaims) (ManageRegions []*response.AccountArea, err error) {

	var SearchAccount *admin.Account

	var rootRegions []*admin.Region

	err = global.OC_DB.Transaction(func(tx *gorm.DB) error {

		if err := tx.Where("username = ?", claims.Username).First(&SearchAccount).Error; err != nil {
			return errors.New("无该账号信息")
		} else {
			var ids = utils.BeLongCity(SearchAccount.RegionLink)
			// 搜索区域
			tx.Find(&rootRegions, ids)
			tx.Model(&admin.Region{}).Select("*,CONCAT(link,id,',') AS region_link").Where("link LIKE ?", fmt.Sprintf("%v%%", SearchAccount.RegionLink)).Scan(&ManageRegions)
			ManageRegions = utils.BuildRegionForestV2(ManageRegions)

			return nil
		}
	})

	return ManageRegions, err
}

// 设置账号区域
func (a *Account) SetAccountRegion(claims tools.BaseClaims, ids request.SetRegion) error {

	var parentAccount *admin.Account
	var nowAccount *admin.Account
	var associationRegion []*admin.Region
	// 找出父账号的管理的区域
	err := global.OC_DB.Transaction(func(tx *gorm.DB) error {

		err := tx.Where("username = ?", claims.Username).First(&parentAccount).Error

		if err != nil {
			return errors.New("无该账号信息")
		}

		err = tx.Where("username = ?", ids.Username).First(&nowAccount).Error

		if err != nil {
			return errors.New("找不到该角色")
		}

		// if !nowAccount.CanBeSetRegion {
		// 	return errors.New("该账户无法被设置区域")
		// }

		match, _ := regexp.MatchString(fmt.Sprintf("^%v", parentAccount.AccountLink), nowAccount.AccountLink)

		if !match {
			return errors.New("你无权修改该账户信息")
		}

		tx.Where("id IN ?", ids.IDS).Find(&associationRegion)

		if !utils.AllEqual(associationRegion) {
			return errors.New("你要配置的区域必须在同一管理区域内")
		}

		if !utils.AllSameRegion(associationRegion, nowAccount.RegionType) {
			return errors.New("你要配置的账号无法配置该等级的区域")
		}

		var manageIds []uint // 找出要添加的地区中不属于该账号的而且不为0的

		for _, v := range associationRegion {
			if v.ManageId != 0 && v.ManageId != nowAccount.ID {
				manageIds = append(manageIds, v.ManageId)
			}
		}

		manageIds = utils.UniqueUintSlice(manageIds) //去重

		if len(manageIds) != 0 {
			return errors.New("你要配置的区域已有代理人或者管理者，请先解除该地区管理者的绑定")
		}

		tx.Model(&nowAccount).Association("Regions").Replace(associationRegion) //替换当前的地区管理人

		var region_arr []string

		for _, v := range associationRegion {
			region_arr = append(region_arr, fmt.Sprintf("%v%v,", v.Link, v.ID))
		}
		tx.Model(&nowAccount).Association("Regions").Replace(associationRegion) //添加关联
		var regionConfig map[string]interface{}
		if len(ids.IDS) != 0 {
			regionConfig = map[string]interface{}{"region_link": strings.Join(region_arr, "|"), "is_set_region": true}
		} else {
			regionConfig = map[string]interface{}{"region_link": parentAccount.RegionLink, "is_set_region": false}
		}

		tx.Model(&admin.Account{}).Where("username = ?", ids.Username).Updates(regionConfig)

		if utils.IsAllCity(associationRegion) {

			var configs []int

			for _, v := range associationRegion {
				configs = append(configs, int(v.ID))
			}

			err = CitySettingService.CreateCityConfig(configs, int(nowAccount.ID))

			if err != nil {
				return err
			}
		}

		return nil

	})

	return err
}

// 根据账号获取他的子角色
func (a *Account) GetRoleByAccount(claims tools.BaseClaims) (roles []*admin.Role, err error) {

	var SearchAccount *admin.Account

	var parse *utils.ParseAccount

	err = global.OC_DB.Transaction(func(tx *gorm.DB) error {

		err1 := tx.Scopes(parse.Parse(claims, tx)).First(&SearchAccount).Error

		if err1 != nil {
			return errors.New("无该账号信息")
		}

		tx.Where("p_id = ?", SearchAccount.RoleId).Omit("link").Find(&roles)

		return nil

	})

	return roles, err
}

// 获取账号当前可以设置的区域
func (a *Account) GetCanSetRegionByAccount(claims tools.BaseClaims) (regions []*admin.Region, err error) {

	var SearchAccount *admin.Account

	var parse *utils.ParseAccount

	err = global.OC_DB.Transaction(func(tx *gorm.DB) error {

		err1 := tx.Scopes(parse.Parse(claims, tx)).First(&SearchAccount).Error

		if err1 != nil {
			return errors.New("无该账号信息")
		}

		var newReg = fmt.Sprintf("(%v)$", SearchAccount.RegionLink)

		tx.Where("link REGEXP ?", newReg).Omit("link").Find(&regions)

		return nil

	})

	return regions, err
}

// 删除
func (a *Account) Delete(ids []int, claims tools.BaseClaims) (err error) {

	var account *admin.Account

	var accounts []*admin.Account

	err = global.OC_DB.Scopes(dao.ParseAccountDao.Parse(claims, global.OC_DB)).First(&account).Error

	if err != nil {
		return errors.New("无该账号信息")
	}

	global.OC_DB.Find(&accounts, ids)

	if !utils.IsBelongThisAccount(accounts, account) {
		return errors.New("你无权删除该账号")
	}

	global.OC_DB.Unscoped().Delete(&admin.Account{}, ids)

	return nil

}

func (a *Account) SetStatus(info *request.SetStatus, claims tools.BaseClaims) (err error) {

	var account *admin.Account

	var setAccount *admin.Account

	err = global.OC_DB.Scopes(dao.ParseAccountDao.Parse(claims, global.OC_DB)).First(&account).Error

	if err != nil {
		return errors.New("无该账号信息")
	}

	err = global.OC_DB.First(&setAccount, info.ID).Error

	if err != nil {
		return errors.New("位置错误500")
	}

	match, _ := regexp.MatchString(fmt.Sprintf("(^%v)", account.AccountLink), setAccount.AccountLink)

	if !match {
		return errors.New("你无权设置该账号")
	}

	global.OC_DB.Model(&admin.Account{}).Where("id = ?", info.ID).Update("status", info.Status)

	return nil

}

var AccountService = new(Account)
